package com.github.config;

import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.LinkedHashMap;
import java.util.Map;

/**
 * @author subeiLY
 * @create 2022-01-31 20:43
 */
// 声明为配置类
@Configuration
public class ShiroConfig {
    // 创建 ShiroFilterFactoryBean
    @Bean
    public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager securityManager) {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new
                ShiroFilterFactoryBean();
        // 设置安全管理器
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        /*
        添加Shiro内置过滤器，常用的有如下过滤器：
        anon： 无需认证就可以访问
        authc： 必须认证才可以访问
        user： 如果使用了记住我功能就可以直接访问
        perms: 拥有某个资源权限才可以访问
        role： 拥有某个角色权限才可以访问
        */
        Map<String, String> filterMap = new LinkedHashMap<String, String>();
//        filterMap.put("/user/add","authc");
//        filterMap.put("/user/update","authc");
        filterMap.put("/user/*", "authc");

        // 登录不需要授权-白名单
        filterMap.put("/user/login", "anon");
        // 登录页面不需要授权-白名单
        filterMap.put("/toLogin", "anon");
        // 返回json无权限-白名单
        filterMap.put("/noauth", "anon");

        // TODO [重要] 定义了所有访问权限的范围, 存在的才管控,不存在不管控
        filterMap.put("/user/add", "perms[user:add]");
        filterMap.put("/user/update", "perms[user:update]");
//        filterMap.put("/user/add1", "perms[user:add1]"); // 对 /user/add1 路径强制要求 user:add1 权限
//        filterMap.put("/**", "authc"); // 对所有路径强制要求认证

        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap);
        // 未认证的发送登录页面,, 认证但是无权限的直接返回json数据,怎么处理
        shiroFilterFactoryBean.setUnauthorizedUrl("/noauth");
        // 修改到要跳转的login页面；
        shiroFilterFactoryBean.setLoginUrl("/toLogin");
        return shiroFilterFactoryBean;
    }

//    @Bean
//    public EhCacheManager getEhCacheManager() {
//        net.sf.ehcache.CacheManager cacheManager = net.sf.ehcache.CacheManager.getCacheManager("seekdi");
//        EhCacheManager em = new EhCacheManager();
//        if (StringUtils.isNull(cacheManager)) {
//            em.setCacheManager(new net.sf.ehcache.CacheManager(getCacheManagerConfigFileInputStream()));
//            return em;
//        } else {
//            em.setCacheManager(cacheManager);
//            return em;
//        }
//    }

    // 创建 DefaultWebSecurityManager
    @Bean(name = "securityManager")
    public DefaultWebSecurityManager securityManager(@Qualifier("userRealm") UserRealm userRealm) {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        // 关联Realm
        securityManager.setRealm(userRealm);
        // 注入缓存管理器;
//        securityManager.setCacheManager(getEhCacheManager());
        // session管理器
//        securityManager.setSessionManager(sessionManager());
        return securityManager;
    }

    // 配置ShiroDialect：方言，用于 thymeleaf 和 shiro 标签配合使用
    @Bean
    public ShiroDialect getShiroDialect() {
        return new ShiroDialect();
    }

    // 创建 realm 对象
    @Bean
    public UserRealm userRealm() {
        return new UserRealm();
    }
    
    /**
     * 开启Shiro注解模式，可以在Controller中的方法上使用注解
     */
    @Bean
    public static org.apache.shiro.spring.LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
        return new org.apache.shiro.spring.LifecycleBeanPostProcessor();
    }
    
    /**
     * 开启Shiro的注解(如@RequiresRoles,@RequiresPermissions)，需借助SpringAOP扫描使用Shiro注解的类,并在必要时进行安全逻辑验证
     */
    @Bean
    public org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
        org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator = new org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator();
        // 强制使用cglib，防止重复代理和可能引起代理出错的问题
        defaultAdvisorAutoProxyCreator.setProxyTargetClass(true);
        return defaultAdvisorAutoProxyCreator;
    }
    
    /**
     * 配置Shiro注解模式的支持
     */
    @Bean
    public org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(@Qualifier("securityManager") DefaultWebSecurityManager securityManager) {
        org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor advisor = new org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor();
        advisor.setSecurityManager(securityManager);
        return advisor;
    }

}
